1   /*
2    * Copyright (C) 2009 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.cache;
18  
19  import static com.google.common.base.Preconditions.checkArgument;
20  import static com.google.common.base.Preconditions.checkNotNull;
21  import static com.google.common.base.Preconditions.checkState;
22  
23  import com.google.common.annotations.GwtCompatible;
24  import com.google.common.base.Ascii;
25  import com.google.common.base.Equivalence;
26  import com.google.common.base.MoreObjects;
27  import com.google.common.base.Supplier;
28  import com.google.common.base.Suppliers;
29  import com.google.common.base.Ticker;
30  import com.google.common.cache.AbstractCache.SimpleStatsCounter;
31  import com.google.common.cache.AbstractCache.StatsCounter;
32  import com.google.common.cache.LocalCache.Strength;
33  
34  import java.util.concurrent.TimeUnit;
35  import java.util.logging.Level;
36  import java.util.logging.Logger;
37  
38  import javax.annotation.CheckReturnValue;
39  
40  /**
41   * <p>A builder of {@link LoadingCache} and {@link Cache} instances having any combination of the
42   * following features:
43   *
44   * <ul>
45   * <li>automatic loading of entries into the cache
46   * <li>least-recently-used eviction when a maximum size is exceeded
47   * <li>time-based expiration of entries, measured since last access or last write
48   * <li>keys automatically wrapped in {@linkplain WeakReference weak} references
49   * <li>values automatically wrapped in {@linkplain WeakReference weak} or
50   *     {@linkplain SoftReference soft} references
51   * <li>notification of evicted (or otherwise removed) entries
52   * <li>accumulation of cache access statistics
53   * </ul>
54   *
55   * <p>These features are all optional; caches can be created using all or none of them. By default
56   * cache instances created by {@code CacheBuilder} will not perform any type of eviction.
57   *
58   * <p>Usage example: <pre>   {@code
59   *
60   *   LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
61   *       .maximumSize(10000)
62   *       .expireAfterWrite(10, TimeUnit.MINUTES)
63   *       .removalListener(MY_LISTENER)
64   *       .build(
65   *           new CacheLoader<Key, Graph>() {
66   *             public Graph load(Key key) throws AnyException {
67   *               return createExpensiveGraph(key);
68   *             }
69   *           });}</pre>
70   *
71   * <p>Or equivalently, <pre>   {@code
72   *
73   *   // In real life this would come from a command-line flag or config file
74   *   String spec = "maximumSize=10000,expireAfterWrite=10m";
75   *
76   *   LoadingCache<Key, Graph> graphs = CacheBuilder.from(spec)
77   *       .removalListener(MY_LISTENER)
78   *       .build(
79   *           new CacheLoader<Key, Graph>() {
80   *             public Graph load(Key key) throws AnyException {
81   *               return createExpensiveGraph(key);
82   *             }
83   *           });}</pre>
84   *
85   * <p>The returned cache is implemented as a hash table with similar performance characteristics to
86   * {@link ConcurrentHashMap}. It implements all optional operations of the {@link LoadingCache} and
87   * {@link Cache} interfaces. The {@code asMap} view (and its collection views) have <i>weakly
88   * consistent iterators</i>. This means that they are safe for concurrent use, but if other threads
89   * modify the cache after the iterator is created, it is undefined which of these changes, if any,
90   * are reflected in that iterator. These iterators never throw {@link
91   * ConcurrentModificationException}.
92   *
93   * <p><b>Note:</b> by default, the returned cache uses equality comparisons (the
94   * {@link Object#equals equals} method) to determine equality for keys or values. However, if
95   * {@link #weakKeys} was specified, the cache uses identity ({@code ==})
96   * comparisons instead for keys. Likewise, if {@link #weakValues} or {@link #softValues} was
97   * specified, the cache uses identity comparisons for values.
98   *
99   * <p>Entries are automatically evicted from the cache when any of
100  * {@linkplain #maximumSize(long) maximumSize}, {@linkplain #maximumWeight(long) maximumWeight},
101  * {@linkplain #expireAfterWrite expireAfterWrite},
102  * {@linkplain #expireAfterAccess expireAfterAccess}, {@linkplain #weakKeys weakKeys},
103  * {@linkplain #weakValues weakValues}, or {@linkplain #softValues softValues} are requested.
104  *
105  * <p>If {@linkplain #maximumSize(long) maximumSize} or
106  * {@linkplain #maximumWeight(long) maximumWeight} is requested entries may be evicted on each cache
107  * modification.
108  *
109  * <p>If {@linkplain #expireAfterWrite expireAfterWrite} or
110  * {@linkplain #expireAfterAccess expireAfterAccess} is requested entries may be evicted on each
111  * cache modification, on occasional cache accesses, or on calls to {@link Cache#cleanUp}. Expired
112  * entries may be counted by {@link Cache#size}, but will never be visible to read or write
113  * operations.
114  *
115  * <p>If {@linkplain #weakKeys weakKeys}, {@linkplain #weakValues weakValues}, or
116  * {@linkplain #softValues softValues} are requested, it is possible for a key or value present in
117  * the cache to be reclaimed by the garbage collector. Entries with reclaimed keys or values may be
118  * removed from the cache on each cache modification, on occasional cache accesses, or on calls to
119  * {@link Cache#cleanUp}; such entries may be counted in {@link Cache#size}, but will never be
120  * visible to read or write operations.
121  *
122  * <p>Certain cache configurations will result in the accrual of periodic maintenance tasks which
123  * will be performed during write operations, or during occasional read operations in the absence of
124  * writes. The {@link Cache#cleanUp} method of the returned cache will also perform maintenance, but
125  * calling it should not be necessary with a high throughput cache. Only caches built with
126  * {@linkplain #removalListener removalListener}, {@linkplain #expireAfterWrite expireAfterWrite},
127  * {@linkplain #expireAfterAccess expireAfterAccess}, {@linkplain #weakKeys weakKeys},
128  * {@linkplain #weakValues weakValues}, or {@linkplain #softValues softValues} perform periodic
129  * maintenance.
130  *
131  * <p>The caches produced by {@code CacheBuilder} are serializable, and the deserialized caches
132  * retain all the configuration properties of the original cache. Note that the serialized form does
133  * <i>not</i> include cache contents, but only configuration.
134  *
135  * <p>See the Guava User Guide article on <a href=
136  * "http://code.google.com/p/guava-libraries/wiki/CachesExplained">caching</a> for a higher-level
137  * explanation.
138  *
139  * @param <K> the base key type for all caches created by this builder
140  * @param <V> the base value type for all caches created by this builder
141  * @author Charles Fry
142  * @author Kevin Bourrillion
143  * @since 10.0
144  */
145 @GwtCompatible(emulated = true)
146 public final class CacheBuilder<K, V> {
147   private static final int DEFAULT_INITIAL_CAPACITY = 16;
148   private static final int DEFAULT_CONCURRENCY_LEVEL = 4;
149   private static final int DEFAULT_EXPIRATION_NANOS = 0;
150   private static final int DEFAULT_REFRESH_NANOS = 0;
151 
152   static final Supplier<? extends StatsCounter> NULL_STATS_COUNTER = Suppliers.ofInstance(
153       new StatsCounter() {
154         @Override
155         public void recordHits(int count) {}
156 
157         @Override
158         public void recordMisses(int count) {}
159 
160         @Override
161         public void recordLoadSuccess(long loadTime) {}
162 
163         @Override
164         public void recordLoadException(long loadTime) {}
165 
166         @Override
167         public void recordEviction() {}
168 
169         @Override
170         public CacheStats snapshot() {
171           return EMPTY_STATS;
172         }
173       });
174   static final CacheStats EMPTY_STATS = new CacheStats(0, 0, 0, 0, 0, 0);
175 
176   static final Supplier<StatsCounter> CACHE_STATS_COUNTER =
177       new Supplier<StatsCounter>() {
178     @Override
179     public StatsCounter get() {
180       return new SimpleStatsCounter();
181     }
182   };
183 
184   enum NullListener implements RemovalListener<Object, Object> {
185     INSTANCE;
186 
187     @Override
188     public void onRemoval(RemovalNotification<Object, Object> notification) {}
189   }
190 
191   enum OneWeigher implements Weigher<Object, Object> {
192     INSTANCE;
193 
194     @Override
195     public int weigh(Object key, Object value) {
196       return 1;
197     }
198   }
199 
200   static final Ticker NULL_TICKER = new Ticker() {
201     @Override
202     public long read() {
203       return 0;
204     }
205   };
206 
207   private static final Logger logger = Logger.getLogger(CacheBuilder.class.getName());
208 
209   static final int UNSET_INT = -1;
210 
211   boolean strictParsing = true;
212 
213   int initialCapacity = UNSET_INT;
214   int concurrencyLevel = UNSET_INT;
215   long maximumSize = UNSET_INT;
216   long maximumWeight = UNSET_INT;
217   Weigher<? super K, ? super V> weigher;
218 
219   Strength keyStrength;
220   Strength valueStrength;
221 
222   long expireAfterWriteNanos = UNSET_INT;
223   long expireAfterAccessNanos = UNSET_INT;
224   long refreshNanos = UNSET_INT;
225 
226   Equivalence<Object> keyEquivalence;
227   Equivalence<Object> valueEquivalence;
228 
229   RemovalListener<? super K, ? super V> removalListener;
230   Ticker ticker;
231 
232   Supplier<? extends StatsCounter> statsCounterSupplier = NULL_STATS_COUNTER;
233 
234   // TODO(fry): make constructor private and update tests to use newBuilder
235   CacheBuilder() {}
236 
237   /**
238    * Constructs a new {@code CacheBuilder} instance with default settings, including strong keys,
239    * strong values, and no automatic eviction of any kind.
240    */
241   public static CacheBuilder<Object, Object> newBuilder() {
242     return new CacheBuilder<Object, Object>();
243   }
244 
245   Equivalence<Object> getKeyEquivalence() {
246     return MoreObjects.firstNonNull(keyEquivalence, getKeyStrength().defaultEquivalence());
247   }
248 
249   Equivalence<Object> getValueEquivalence() {
250     return MoreObjects.firstNonNull(valueEquivalence, getValueStrength().defaultEquivalence());
251   }
252 
253   /**
254    * Sets the minimum total size for the internal hash tables. For example, if the initial capacity
255    * is {@code 60}, and the concurrency level is {@code 8}, then eight segments are created, each
256    * having a hash table of size eight. Providing a large enough estimate at construction time
257    * avoids the need for expensive resizing operations later, but setting this value unnecessarily
258    * high wastes memory.
259    *
260    * @throws IllegalArgumentException if {@code initialCapacity} is negative
261    * @throws IllegalStateException if an initial capacity was already set
262    */
263   public CacheBuilder<K, V> initialCapacity(int initialCapacity) {
264     checkState(this.initialCapacity == UNSET_INT, "initial capacity was already set to %s",
265         this.initialCapacity);
266     checkArgument(initialCapacity >= 0);
267     this.initialCapacity = initialCapacity;
268     return this;
269   }
270 
271   int getInitialCapacity() {
272     return (initialCapacity == UNSET_INT) ? DEFAULT_INITIAL_CAPACITY : initialCapacity;
273   }
274 
275   /**
276    * Guides the allowed concurrency among update operations. Used as a hint for internal sizing. The
277    * table is internally partitioned to try to permit the indicated number of concurrent updates
278    * without contention. Because assignment of entries to these partitions is not necessarily
279    * uniform, the actual concurrency observed may vary. Ideally, you should choose a value to
280    * accommodate as many threads as will ever concurrently modify the table. Using a significantly
281    * higher value than you need can waste space and time, and a significantly lower value can lead
282    * to thread contention. But overestimates and underestimates within an order of magnitude do not
283    * usually have much noticeable impact. A value of one permits only one thread to modify the cache
284    * at a time, but since read operations and cache loading computations can proceed concurrently,
285    * this still yields higher concurrency than full synchronization.
286    *
287    * <p> Defaults to 4. <b>Note:</b>The default may change in the future. If you care about this
288    * value, you should always choose it explicitly.
289    *
290    * <p>The current implementation uses the concurrency level to create a fixed number of hashtable
291    * segments, each governed by its own write lock. The segment lock is taken once for each explicit
292    * write, and twice for each cache loading computation (once prior to loading the new value,
293    * and once after loading completes). Much internal cache management is performed at the segment
294    * granularity. For example, access queues and write queues are kept per segment when they are
295    * required by the selected eviction algorithm. As such, when writing unit tests it is not
296    * uncommon to specify {@code concurrencyLevel(1)} in order to achieve more deterministic eviction
297    * behavior.
298    *
299    * <p>Note that future implementations may abandon segment locking in favor of more advanced
300    * concurrency controls.
301    *
302    * @throws IllegalArgumentException if {@code concurrencyLevel} is nonpositive
303    * @throws IllegalStateException if a concurrency level was already set
304    */
305   public CacheBuilder<K, V> concurrencyLevel(int concurrencyLevel) {
306     checkState(this.concurrencyLevel == UNSET_INT, "concurrency level was already set to %s",
307         this.concurrencyLevel);
308     checkArgument(concurrencyLevel > 0);
309     this.concurrencyLevel = concurrencyLevel;
310     return this;
311   }
312 
313   int getConcurrencyLevel() {
314     return (concurrencyLevel == UNSET_INT) ? DEFAULT_CONCURRENCY_LEVEL : concurrencyLevel;
315   }
316 
317   /**
318    * Specifies the maximum number of entries the cache may contain. Note that the cache <b>may evict
319    * an entry before this limit is exceeded</b>. As the cache size grows close to the maximum, the
320    * cache evicts entries that are less likely to be used again. For example, the cache may evict an
321    * entry because it hasn't been used recently or very often.
322    *
323    * <p>When {@code size} is zero, elements will be evicted immediately after being loaded into the
324    * cache. This can be useful in testing, or to disable caching temporarily without a code change.
325    *
326    * <p>This feature cannot be used in conjunction with {@link #maximumWeight}.
327    *
328    * @param size the maximum size of the cache
329    * @throws IllegalArgumentException if {@code size} is negative
330    * @throws IllegalStateException if a maximum size or weight was already set
331    */
332   public CacheBuilder<K, V> maximumSize(long size) {
333     checkState(this.maximumSize == UNSET_INT, "maximum size was already set to %s",
334         this.maximumSize);
335     checkState(this.maximumWeight == UNSET_INT, "maximum weight was already set to %s",
336         this.maximumWeight);
337     checkState(this.weigher == null, "maximum size can not be combined with weigher");
338     checkArgument(size >= 0, "maximum size must not be negative");
339     this.maximumSize = size;
340     return this;
341   }
342 
343   long getMaximumWeight() {
344     if (expireAfterWriteNanos == 0 || expireAfterAccessNanos == 0) {
345       return 0;
346     }
347     return (weigher == null) ? maximumSize : maximumWeight;
348   }
349 
350   // Make a safe contravariant cast now so we don't have to do it over and over.
351   @SuppressWarnings("unchecked")
352   <K1 extends K, V1 extends V> Weigher<K1, V1> getWeigher() {
353     return (Weigher<K1, V1>) MoreObjects.firstNonNull(weigher, OneWeigher.INSTANCE);
354   }
355 
356   CacheBuilder<K, V> setKeyStrength(Strength strength) {
357     checkState(keyStrength == null, "Key strength was already set to %s", keyStrength);
358     keyStrength = checkNotNull(strength);
359     return this;
360   }
361 
362   Strength getKeyStrength() {
363     return MoreObjects.firstNonNull(keyStrength, Strength.STRONG);
364   }
365 
366   CacheBuilder<K, V> setValueStrength(Strength strength) {
367     checkState(valueStrength == null, "Value strength was already set to %s", valueStrength);
368     valueStrength = checkNotNull(strength);
369     return this;
370   }
371 
372   Strength getValueStrength() {
373     return MoreObjects.firstNonNull(valueStrength, Strength.STRONG);
374   }
375 
376   /**
377    * Specifies that each entry should be automatically removed from the cache once a fixed duration
378    * has elapsed after the entry's creation, or the most recent replacement of its value.
379    *
380    * <p>When {@code duration} is zero, this method hands off to
381    * {@link #maximumSize(long) maximumSize}{@code (0)}, ignoring any otherwise-specificed maximum
382    * size or weight. This can be useful in testing, or to disable caching temporarily without a code
383    * change.
384    *
385    * <p>Expired entries may be counted in {@link Cache#size}, but will never be visible to read or
386    * write operations. Expired entries are cleaned up as part of the routine maintenance described
387    * in the class javadoc.
388    *
389    * @param duration the length of time after an entry is created that it should be automatically
390    *     removed
391    * @param unit the unit that {@code duration} is expressed in
392    * @throws IllegalArgumentException if {@code duration} is negative
393    * @throws IllegalStateException if the time to live or time to idle was already set
394    */
395   public CacheBuilder<K, V> expireAfterWrite(long duration, TimeUnit unit) {
396     checkState(expireAfterWriteNanos == UNSET_INT, "expireAfterWrite was already set to %s ns",
397         expireAfterWriteNanos);
398     checkArgument(duration >= 0, "duration cannot be negative: %s %s", duration, unit);
399     this.expireAfterWriteNanos = unit.toNanos(duration);
400     return this;
401   }
402 
403   long getExpireAfterWriteNanos() {
404     return (expireAfterWriteNanos == UNSET_INT) ? DEFAULT_EXPIRATION_NANOS : expireAfterWriteNanos;
405   }
406 
407   /**
408    * Specifies that each entry should be automatically removed from the cache once a fixed duration
409    * has elapsed after the entry's creation, the most recent replacement of its value, or its last
410    * access. Access time is reset by all cache read and write operations (including
411    * {@code Cache.asMap().get(Object)} and {@code Cache.asMap().put(K, V)}), but not by operations
412    * on the collection-views of {@link Cache#asMap}.
413    *
414    * <p>When {@code duration} is zero, this method hands off to
415    * {@link #maximumSize(long) maximumSize}{@code (0)}, ignoring any otherwise-specificed maximum
416    * size or weight. This can be useful in testing, or to disable caching temporarily without a code
417    * change.
418    *
419    * <p>Expired entries may be counted in {@link Cache#size}, but will never be visible to read or
420    * write operations. Expired entries are cleaned up as part of the routine maintenance described
421    * in the class javadoc.
422    *
423    * @param duration the length of time after an entry is last accessed that it should be
424    *     automatically removed
425    * @param unit the unit that {@code duration} is expressed in
426    * @throws IllegalArgumentException if {@code duration} is negative
427    * @throws IllegalStateException if the time to idle or time to live was already set
428    */
429   public CacheBuilder<K, V> expireAfterAccess(long duration, TimeUnit unit) {
430     checkState(expireAfterAccessNanos == UNSET_INT, "expireAfterAccess was already set to %s ns",
431         expireAfterAccessNanos);
432     checkArgument(duration >= 0, "duration cannot be negative: %s %s", duration, unit);
433     this.expireAfterAccessNanos = unit.toNanos(duration);
434     return this;
435   }
436 
437   long getExpireAfterAccessNanos() {
438     return (expireAfterAccessNanos == UNSET_INT)
439         ? DEFAULT_EXPIRATION_NANOS : expireAfterAccessNanos;
440   }
441 
442   long getRefreshNanos() {
443     return (refreshNanos == UNSET_INT) ? DEFAULT_REFRESH_NANOS : refreshNanos;
444   }
445 
446   /**
447    * Specifies a nanosecond-precision time source for use in determining when entries should be
448    * expired. By default, {@link System#nanoTime} is used.
449    *
450    * <p>The primary intent of this method is to facilitate testing of caches which have been
451    * configured with {@link #expireAfterWrite} or {@link #expireAfterAccess}.
452    *
453    * @throws IllegalStateException if a ticker was already set
454    */
455   public CacheBuilder<K, V> ticker(Ticker ticker) {
456     checkState(this.ticker == null);
457     this.ticker = checkNotNull(ticker);
458     return this;
459   }
460 
461   Ticker getTicker(boolean recordsTime) {
462     if (ticker != null) {
463       return ticker;
464     }
465     return recordsTime ? Ticker.systemTicker() : NULL_TICKER;
466   }
467 
468   /**
469    * Specifies a listener instance that caches should notify each time an entry is removed for any
470    * {@linkplain RemovalCause reason}. Each cache created by this builder will invoke this listener
471    * as part of the routine maintenance described in the class documentation above.
472    *
473    * <p><b>Warning:</b> after invoking this method, do not continue to use <i>this</i> cache
474    * builder reference; instead use the reference this method <i>returns</i>. At runtime, these
475    * point to the same instance, but only the returned reference has the correct generic type
476    * information so as to ensure type safety. For best results, use the standard method-chaining
477    * idiom illustrated in the class documentation above, configuring a builder and building your
478    * cache in a single statement. Failure to heed this advice can result in a {@link
479    * ClassCastException} being thrown by a cache operation at some <i>undefined</i> point in the
480    * future.
481    *
482    * <p><b>Warning:</b> any exception thrown by {@code listener} will <i>not</i> be propagated to
483    * the {@code Cache} user, only logged via a {@link Logger}.
484    *
485    * @return the cache builder reference that should be used instead of {@code this} for any
486    *     remaining configuration and cache building
487    * @throws IllegalStateException if a removal listener was already set
488    */
489   @CheckReturnValue
490   public <K1 extends K, V1 extends V> CacheBuilder<K1, V1> removalListener(
491       RemovalListener<? super K1, ? super V1> listener) {
492     checkState(this.removalListener == null);
493 
494     // safely limiting the kinds of caches this can produce
495     @SuppressWarnings("unchecked")
496     CacheBuilder<K1, V1> me = (CacheBuilder<K1, V1>) this;
497     me.removalListener = checkNotNull(listener);
498     return me;
499   }
500 
501   // Make a safe contravariant cast now so we don't have to do it over and over.
502   @SuppressWarnings("unchecked")
503   <K1 extends K, V1 extends V> RemovalListener<K1, V1> getRemovalListener() {
504     return (RemovalListener<K1, V1>)
505         MoreObjects.firstNonNull(removalListener, NullListener.INSTANCE);
506   }
507 
508   /**
509    * Enable the accumulation of {@link CacheStats} during the operation of the cache. Without this
510    * {@link Cache#stats} will return zero for all statistics. Note that recording stats requires
511    * bookkeeping to be performed with each operation, and thus imposes a performance penalty on
512    * cache operation.
513    *
514    * @since 12.0 (previously, stats collection was automatic)
515    */
516   public CacheBuilder<K, V> recordStats() {
517     statsCounterSupplier = CACHE_STATS_COUNTER;
518     return this;
519   }
520   
521   boolean isRecordingStats() {
522     return statsCounterSupplier == CACHE_STATS_COUNTER;
523   }
524 
525   Supplier<? extends StatsCounter> getStatsCounterSupplier() {
526     return statsCounterSupplier;
527   }
528 
529   /**
530    * Builds a cache, which either returns an already-loaded value for a given key or atomically
531    * computes or retrieves it using the supplied {@code CacheLoader}. If another thread is currently
532    * loading the value for this key, simply waits for that thread to finish and returns its
533    * loaded value. Note that multiple threads can concurrently load values for distinct keys.
534    *
535    * <p>This method does not alter the state of this {@code CacheBuilder} instance, so it can be
536    * invoked again to create multiple independent caches.
537    *
538    * @param loader the cache loader used to obtain new values
539    * @return a cache having the requested features
540    */
541   public <K1 extends K, V1 extends V> LoadingCache<K1, V1> build(
542       CacheLoader<? super K1, V1> loader) {
543     checkWeightWithWeigher();
544     return new LocalCache.LocalLoadingCache<K1, V1>(this, loader);
545   }
546 
547   /**
548    * Builds a cache which does not automatically load values when keys are requested.
549    *
550    * <p>Consider {@link #build(CacheLoader)} instead, if it is feasible to implement a
551    * {@code CacheLoader}.
552    *
553    * <p>This method does not alter the state of this {@code CacheBuilder} instance, so it can be
554    * invoked again to create multiple independent caches.
555    *
556    * @return a cache having the requested features
557    * @since 11.0
558    */
559   public <K1 extends K, V1 extends V> Cache<K1, V1> build() {
560     checkWeightWithWeigher();
561     checkNonLoadingCache();
562     return new LocalCache.LocalManualCache<K1, V1>(this);
563   }
564 
565   private void checkNonLoadingCache() {
566     checkState(refreshNanos == UNSET_INT, "refreshAfterWrite requires a LoadingCache");
567   }
568 
569   private void checkWeightWithWeigher() {
570     if (weigher == null) {
571       checkState(maximumWeight == UNSET_INT, "maximumWeight requires weigher");
572     } else {
573       if (strictParsing) {
574         checkState(maximumWeight != UNSET_INT, "weigher requires maximumWeight");
575       } else {
576         if (maximumWeight == UNSET_INT) {
577           logger.log(Level.WARNING, "ignoring weigher specified without maximumWeight");
578         }
579       }
580     }
581   }
582 
583   /**
584    * Returns a string representation for this CacheBuilder instance. The exact form of the returned
585    * string is not specified.
586    */
587   @Override
588   public String toString() {
589     MoreObjects.ToStringHelper s = MoreObjects.toStringHelper(this);
590     if (initialCapacity != UNSET_INT) {
591       s.add("initialCapacity", initialCapacity);
592     }
593     if (concurrencyLevel != UNSET_INT) {
594       s.add("concurrencyLevel", concurrencyLevel);
595     }
596     if (maximumSize != UNSET_INT) {
597       s.add("maximumSize", maximumSize);
598     }
599     if (maximumWeight != UNSET_INT) {
600       s.add("maximumWeight", maximumWeight);
601     }
602     if (expireAfterWriteNanos != UNSET_INT) {
603       s.add("expireAfterWrite", expireAfterWriteNanos + "ns");
604     }
605     if (expireAfterAccessNanos != UNSET_INT) {
606       s.add("expireAfterAccess", expireAfterAccessNanos + "ns");
607     }
608     if (keyStrength != null) {
609       s.add("keyStrength", Ascii.toLowerCase(keyStrength.toString()));
610     }
611     if (valueStrength != null) {
612       s.add("valueStrength", Ascii.toLowerCase(valueStrength.toString()));
613     }
614     if (keyEquivalence != null) {
615       s.addValue("keyEquivalence");
616     }
617     if (valueEquivalence != null) {
618       s.addValue("valueEquivalence");
619     }
620     if (removalListener != null) {
621       s.addValue("removalListener");
622     }
623     return s.toString();
624   }
625 }
626